package com.jplus.plugins.rpc.core;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jplus.framework.core.CharSet;
import com.jplus.framework.util.FormatUtil;
import com.jplus.plugins.rpc.Constant;
import com.jplus.plugins.rpc.annotation.RpcProvider;
import com.jplus.plugins.rpc.bean.KeyNode;
import com.jplus.plugins.rpc.bean.Service;
import com.jplus.plugins.rpc.bean.ZNode;
import com.jplus.plugins.rpc.impl.AgreementFactory;
import com.jplus.plugins.rpc.impl.handler.ServiceType;

/**
 * 服务端发布服务
 * 
 * @author Yuanqy
 *
 */
public class RpcService {
	private static final Logger logger = LoggerFactory.getLogger(RpcService.class);

	/**
	 * 存放接口名与服务对象之间的映射关系 所有的服务实现都会用到
	 */
	private Map<String, Service> handler = new HashMap<String, Service>();

	/**
	 * 批量创建
	 */
	public void create(Set<Class<?>> rpcServices) throws Exception {
		try {
			if (rpcServices.size() > 0) {
				// ==获取服务和实现类=============
				Service ser = null;
				Set<ServiceType> suport = new HashSet<ServiceType>();// 服务类型
				for (Class<?> cls : rpcServices) {
					ser = new Service(cls.getAnnotation(RpcProvider.class).iface(), cls, cls.getAnnotation(RpcProvider.class));
					handler.put(new KeyNode(ser).MD5(), ser);
					suport.add(ser.getRpcProvider().serviceType());
				}
				// == 创建服务 ===================
				if (AgreementFactory.startServer(handler, suport)) {
					registerZKService();
				}
			}
		} catch (Exception e) {
			logger.error("RPC服务发布失败", e);
			throw e;
		}
	}

	/**
	 * == 注册服务节点 ====================
	 */
	private void registerZKService() {
		try {
			if (ZkFactory.getZK() != null) {
				String node2 = Constant.PROVIDERS;
				Service ser = null;
				RpcProvider rpcp = null;
				for (Entry<String, Service> en : handler.entrySet()) {
					ser = en.getValue();
					rpcp = ser.getRpcProvider();
					String node1 = ser.getIface().getName();
					String node3 = URLEncoder.encode(createZNode(rpcp).toString(), CharSet.Default);
					ZkFactory.createPathLine(FormatUtil.formatParams("{}/{}/{}/{}", Constant.ZK_REGISTRY_PATH, node1, node2, node3)); // 注册服务地址
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private ZNode createZNode(RpcProvider rpcp) {
		return new ZNode(Constant.RPC_LOCAL_HOST, Constant.getHost(rpcp.serviceType()), rpcp.priority(), rpcp.weight(), rpcp.version(), rpcp.serviceType(),
				rpcp.iface().getName());
	}
}
